﻿// Copyright (c) ZhangPeihang. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using LaserMark.DataAccess.Models;
using LaserMark.Models;
using System.IO;
using System.Text;

namespace LaserMark.Extensions
{
    public static class GCode
    {
        public static Original Read(string filepath, List<GCodeOrder> orders)
        {
            var xLeftBottom = orders.First(s => s.Type == GType.XLeftBottom).GOrder;
            var yLeftBottom = orders.First(s => s.Type == GType.YLeftBottom).GOrder;
            var productID = orders.First(s => s.Type == GType.ProductID).GOrder;
            var floorNo = orders.First(s => s.Type == GType.FloorNo).GOrder;
            var markTemplate = orders.Where(s => s.Type == GType.MarkTemplate).ToList();
            var orderNo = orders.First(s => s.Type == GType.OrderNo).GOrder;
            var markPosition = orders.Where(s => s.Type == GType.MarkPosition).ToList();
            var customer = orders.First(s => s.Type == GType.Customer).GOrder;
            var sheetWidth = orders.First(s => s.Type == GType.SheetWidth).GOrder;
            var sheetHeight = orders.First(s => s.Type == GType.SheetHeight).GOrder;
            var xArrow = orders.First(s => s.Type == GType.XArrow).GOrder;
            var yArrow = orders.First(s => s.Type == GType.YArrow).GOrder;
            var basicEdgeorder = orders.Where(s => s.Type == GType.BasicEdge).ToList();
            var hj = orders.First(s => s.Type == GType.HJ).GOrder;
            var markOffset = orders.Where(s => s.Type == GType.MarkOffset).ToList();
            using (var stream = new FileStream(filepath, FileMode.Open, FileAccess.Read))
            {
                var original = new Original();
                original.MarkPoints = new();
                Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
                var reader = new StreamReader(stream, Encoding.GetEncoding("GB2312"));
                while (reader.Peek() != -1)
                {
                    try
                    {
                        var line = reader.ReadLine();
                        if (!string.IsNullOrEmpty(line))
                        {
                            if (line.Contains("G00") && line.Contains("X") && line.Contains("Y") && !line.Contains("Z"))
                            {
                                Point point = new();
                                var arr = line.Split(" ");
                                point.X = Convert.ToDouble(arr[1].Substring(1, arr[1].Length - 1));
                                point.Y = Convert.ToDouble(arr[2].Substring(1, arr[2].Length - 1));
                                while (line.Contains("G00") && line.Contains("X") && line.Contains("Y"))
                                {
                                    var newline = reader.ReadLine();
                                    if (!string.IsNullOrEmpty(newline))
                                    {
                                        if (newline.Contains("G01") && line.Contains("X") && line.Contains("Y"))
                                        {
                                            var arr1 = newline.Split(" ");
                                            point.X1 = Convert.ToDouble(arr1[1].Substring(1, arr1[1].Length - 1));
                                            point.Y1 = Convert.ToDouble(arr1[2].Substring(1, arr1[2].Length - 1));
                                        }
                                        if (newline.Equals("M10") || newline.Equals("M08"))
                                        {
                                            break;
                                        }

                                        if (newline.Equals("M03") || newline.Equals("M09"))
                                        {
                                            continue;
                                        }
                                    }
                                }

                                original.Points.Add(point);
                            }
                            else
                            {
                                var separator = line.IndexOf('=');
                                if (separator == -1)
                                {
                                    continue;
                                }

                                var key = line.Substring(0, separator);
                                var value = line.Substring(separator + 1);
                                if (key.Contains("P3000"))
                                {
                                    original.Width = Convert.ToDouble(value);
                                }

                                if (key.Contains("P3001"))
                                {
                                    original.Height = Convert.ToDouble(value);
                                }

                                if (key.Contains("P3002"))
                                {
                                    original.TrimLeft = Convert.ToDouble(value);
                                }

                                if (key.Contains("P3003"))
                                {
                                    original.TrimBottom = Convert.ToDouble(value);
                                }

                                if (key.Contains("P3004"))
                                {
                                    original.TrimRight = Convert.ToDouble(value);
                                }


                                if (key.Contains("P3005"))
                                {
                                    original.TrimTop = Convert.ToDouble(value);
                                }

                                if (key.Contains("P3006"))
                                {
                                    original.Price = Convert.ToInt32(value);
                                }

                                if (key.Contains("P3007"))
                                {
                                    original.MaterialQuality = value;
                                }

                                if (key.Contains("P4") && value.Contains("_") && !key.Contains("R"))
                                {
                                    var arr = value.Trim().Split("_");
                                    var count = markTemplate.Where(s => s.GOrder != 0).Count() * 4;
                                    for (int i = 0; i < count / 4; i++)
                                    {
                                        MarkPoint point = new MarkPoint();
                                        point.X = Convert.ToDouble(arr[xLeftBottom]);
                                        point.Y = Convert.ToDouble(arr[yLeftBottom]);
                                        point.SheetWidth = Convert.ToDouble(arr[sheetWidth]);
                                        point.SheetHeight = Convert.ToDouble(arr[sheetHeight]);
                                        point.Type = "G";
                                        point.BasicEdge = Convert.ToDouble(arr[basicEdgeorder[i].GOrder]);
                                        point.IsRotate = Convert.ToDouble(arr[basicEdgeorder[i].GOrder]) == Convert.ToDouble(arr[yArrow]) ? true : false;
                                        point.OrderNo = arr[orderNo];
                                        var n = arr[markTemplate[i].GOrder].Split(" ");
                                        point.Info = Convert.ToInt32(n[0]);
                                        point.Customer = arr[customer];
                                        point.XArrow = Convert.ToDouble(arr[xArrow]);
                                        point.YArrow = Convert.ToDouble(arr[yArrow]);
                                        point.OffsetOrder = Convert.ToInt32(arr[markOffset[i].GOrder]);
                                        point.Position = Enum.Parse<Position>(arr[markPosition[i].GOrder]);
                                        point.HJ = arr[hj];
                                        point.ProductID = arr[productID];
                                        point.FloorNo = arr[floorNo];
                                        original.MarkPoints.Add(point);
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {


                    }
                }

                return original;
            }
        }
    }
}
